package com.hk.weixin.security.miniapp;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.hk.commons.util.AssertUtils;
import com.hk.commons.util.ByteConstants;
import com.hk.commons.util.Constants;
import com.hk.core.authentication.api.UserPrincipal;
import com.hk.core.authentication.api.enums.ThirdAccountType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import java.util.Map;
import java.util.Objects;
import java.util.function.Function;


/**
 * 微信小程序认证
 *
 * @author kevin
 * @date 2018年2月8日上午11:25:39
 */
@Slf4j
public record WeiXinMiniappAuthenticationProvider(
        Function<WxMaJscode2SessionResult, UserPrincipal> authenticationFunction) implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        var wxMpUser = (WxMaJscode2SessionResult) authentication.getPrincipal();
        UserPrincipal userPrincipal;
        var wxProp = Map.of(ThirdAccountType.WX_MP.name(), String.valueOf(true),
                Constants.SESSION_KEY, wxMpUser.getSessionKey(),
                Constants.OPEN_ID, wxMpUser.getOpenid(),
                Constants.UNION_ID, wxMpUser.getUnionid());
        if (Objects.isNull(authenticationFunction)) {
            log.warn("authenticationHandler is null.");
            userPrincipal = new UserPrincipal(Long.MAX_VALUE, wxMpUser.getOpenid(), ByteConstants.ZERO);//
        } else {
            userPrincipal = authenticationFunction.apply(wxMpUser);
            AssertUtils.notNull(userPrincipal, "principal Must not be null.");
        }
        userPrincipal.setAdditionalInfo(wxProp);
        return new WeiXinMiniappAuthenticationToken(userPrincipal, null);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return WeiXinMiniappAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
